home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / ar / ar.diffs < prev    next >
Encoding:
Text File  |  1990-11-16  |  64.6 KB  |  2,550 lines

  1. *** /tmp/,RCSt1532831    Thu Nov 15 22:29:13 1990
  2. --- ar.c    Mon Nov 12 11:08:49 1990
  3. ***************
  4. *** 15,25 ****
  5. --- 15,32 ----
  6.      along with this program; if not, write to the Free Software
  7.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  8.   
  9. + #ifndef lint
  10. + static char rcsid[] = "$Header: /sprite/src/cmds/ar/RCS/ar.c,v 1.6 90/11/12 11:08:45 kupfer Exp $";
  11. + #endif
  12.   #include <stdio.h>
  13.   #include <ar.h>
  14.   #include <errno.h>
  15.   #include <sys/types.h>
  16.   #include <sys/stat.h>
  17. + #include <string.h>
  18. + #include <bstring.h>
  19. + #include <assert.h>
  20.   
  21.   #if !defined(A_OUT) && !defined(MACH_O)
  22.   #define A_OUT
  23. ***************
  24. *** 64,76 ****
  25.   #define    bzero(s, size)            memset((s), 0, (size))
  26.   #endif
  27.   
  28. ! /* Locking is normally disabled because fcntl hangs on the Sun
  29.      and it isn't supported properly across NFS anyway.  */
  30.   #ifdef LOCKS
  31.   /* You might need to compile with -I/usr/include/sys if your fcntl.h
  32.      isn't in /usr/include (which is where it should be according to POSIX).  */
  33.   #include <fcntl.h>
  34. ! #endif
  35.   
  36.   /* This structure is used internally to represent the info
  37.      on a member of an archive.  This is to make it easier to change format.  */
  38. --- 71,118 ----
  39.   #define    bzero(s, size)            memset((s), 0, (size))
  40.   #endif
  41.   
  42. ! /* If LOCKS is defined, locking is enabled.  If LOCK_FLOCK is defined,
  43. !    then BSD-style flock() is used.  Otherwise, fcntl() is used.  If
  44. !    LOCKS is not defined, LOCK_FLOCK is irrelevant.
  45. !    Locking is normally disabled because fcntl hangs on the Sun
  46.      and it isn't supported properly across NFS anyway.  */
  47.   #ifdef LOCKS
  48. + /* This flag tells whether the archive was opened read-only or
  49. +    read-write.  It is used for a sanity check before trying to write a
  50. +    new archive.  It is also temporarily as a workaround for a Sprite
  51. +    bug that requires flock() to pass in the type of lock that is being
  52. +    unlocked.  */
  53. + int open_flags;                /* O_RDONLY or O_RDWRITE */
  54. + #ifndef LOCK_FLOCK
  55.   /* You might need to compile with -I/usr/include/sys if your fcntl.h
  56.      isn't in /usr/include (which is where it should be according to POSIX).  */
  57.   #include <fcntl.h>
  58. ! #endif /* LOCK_FLOCK */
  59. ! void lock_a_file (), unlock_a_file ();
  60. ! #endif /* LOCKS */
  61. ! /* This structure represents member names.  It is here to simplify 
  62. !    dealing with different truncation schemes and with names that the
  63. !    user specifies as paths.  Operations deal with the `stored' name,
  64. !    except we maintain a mapping to the name the user gave for
  65. !    reading/writing the member.   If the user didn't specify a name
  66. !    that matches the `stored' name, the `given' name is NULL.  For
  67. !    names provided by the user, the `stored' name is computed
  68. !    immediately, so all member_name objects should have a non-null
  69. !    `stored' name.  */
  70. ! struct member_name {
  71. !   char *given;                /* name given by the user */
  72. !   char *stored;                /* name as stored in the ar header */
  73. ! };
  74. ! #define Empty_Name(name)    ((name)->stored == NULL)
  75.   
  76.   /* This structure is used internally to represent the info
  77.      on a member of an archive.  This is to make it easier to change format.  */
  78. ***************
  79. *** 77,84 ****
  80.   
  81.   struct member_desc
  82.     {
  83. !     /* Name of member.  */
  84. !     char *name;
  85.   
  86.       /* The following fields are stored in the member header as decimal or octal
  87.          numerals, but in this structure they are stored as machine numbers.  */
  88. --- 119,128 ----
  89.   
  90.   struct member_desc
  91.     {
  92. !     /* `given' will be zero if the user didn't specifically name this
  93. !        member.  The name will be empty if this member is marked for
  94. !        deletion.  */
  95. !     struct member_name name;
  96.   
  97.       /* The following fields are stored in the member header as decimal or octal
  98.          numerals, but in this structure they are stored as machine numbers.  */
  99. ***************
  100. *** 112,121 ****
  101.       unsigned long int offset;
  102.     };
  103.   
  104. ! /* Nonzero means it's the name of an existing member;
  105.      position new or moved files with respect to this one.  */
  106.   
  107. ! char *posname;
  108.   
  109.   
  110.   /* How to use `posname':
  111. --- 156,165 ----
  112.       unsigned long int offset;
  113.     };
  114.   
  115. ! /* Nonzero means that it's the name of an existing member;
  116.      position new or moved files with respect to this one.  */
  117.   
  118. ! struct member_name *posname;
  119.   
  120.   
  121.   /* How to use `posname':
  122. ***************
  123. *** 158,173 ****
  124.   
  125.   char *archive;
  126.   
  127. ! /* Descriptor on which we have locked the original archive file,
  128. !    or -1 if this has not been done.  */
  129.   
  130. ! int lock_indesc;
  131.   
  132. ! /* Pointer to tail of `argv', at first subfile name argument,
  133. !  or zero if no such were specified.  */
  134.   
  135. ! char **files;
  136.   
  137.   /* Nonzero means write a __.SYMDEF member into the modified archive.  */
  138.   
  139.   int symdef_flag;
  140. --- 202,230 ----
  141.   
  142.   char *archive;
  143.   
  144. ! /* Descriptor for the archive file.  This descriptor is used for
  145. !    locking the archive.  -1 if the archive is not yet opened.  */
  146.   
  147. ! int arcfd;
  148.   
  149. ! /* File pointer for the archive, used only for reading the archive.  0 
  150. !    if the archive hasn't been opened yet.  */
  151. ! FILE *arcstream;
  152. ! /* (Pointer to) an array of file names specified by the user.  The 
  153. !    last element is a dummy, with an "empty" name.  The remaining
  154. !    elements have both `given' and `header' filled in.  Zero if the
  155. !    user didn't specify any file names.  */
  156. ! struct member_name *file_args;
  157. ! /* *** Lots of globals related to the __.SYMDEF member.***  */
  158.   
  159. ! /* Name "__.SYMDEF", converted to "member_name" form. */
  160.   
  161. + struct member_name symdef_name;
  162.   /* Nonzero means write a __.SYMDEF member into the modified archive.  */
  163.   
  164.   int symdef_flag;
  165. ***************
  166. *** 212,217 ****
  167. --- 269,287 ----
  168.   
  169.   unsigned long int new_strings_size;
  170.   
  171. + /* ***End of __.SYMDEF globals.*** */
  172. + /* Controls the way in which long names are truncated.  If non-zero,
  173. +    SomeVeryLongName.o is converted to SomeVeryLongN.o.  Otherwise, it
  174. +    is converted to SomeVeryLongNam (which is compatible with the BSD
  175. +    ar).  */
  176. + #ifndef GNU_TRUNCATION
  177. + #define GNU_TRUNCATION    1
  178. + #endif
  179. + int gnu_truncation = GNU_TRUNCATION;
  180.   /* An archive map is a chain of these structures.
  181.     Each structure describes one member of the archive.
  182.     The chain is in the same order as the members are.  */
  183. ***************
  184. *** 249,259 ****
  185. --- 319,342 ----
  186.   void two_operations ();
  187.   void usage (), fatal (), error (), error_with_file ();
  188.   void perror_with_name (), pfatal_with_name ();
  189. + void open_archive ();
  190.   void write_archive ();
  191.   void touch_symdef_member ();
  192.   void update_symdefs ();
  193.   void delete_members (), move_members (), replace_members ();
  194.   void quick_append ();
  195. + void init_elt (), mark_as_deleted ();
  196. + int marked_for_deletion ();
  197. + int name_match ();
  198. + void init_name (), free_name_strings ();
  199. + int move_in_map ();
  200. + int filter_symbols ();
  201. + char *user_to_header ();
  202. + struct member_name *make_file_args ();
  203. + void verify_is_archive ();
  204. + #if DEBUG
  205. + void verify_symdefs ();
  206. + #endif
  207.   
  208.   /* Output BYTES of data at BUF to the descriptor DESC.
  209.      FILE is the name of the file (for error messages).  */
  210. ***************
  211. *** 291,302 ****
  212.     posname = 0;
  213.     postype = POS_DEFAULT;
  214.     preserve_dates = 0;
  215.     symdef_flag = 0;
  216.     symdef_exists = 0;
  217.     ignore_symdef = 0;
  218.     symdef_mapelt = 0;
  219. !   files = 0;
  220. !   lock_indesc = -1;
  221.   
  222.     if (argc < 2)
  223.       usage ("too few command arguments", 0);
  224. --- 374,387 ----
  225.     posname = 0;
  226.     postype = POS_DEFAULT;
  227.     preserve_dates = 0;
  228. +   init_name (&symdef_name, "__.SYMDEF");
  229.     symdef_flag = 0;
  230.     symdef_exists = 0;
  231.     ignore_symdef = 0;
  232.     symdef_mapelt = 0;
  233. !   file_args = 0;
  234. !   arcfd = -1;
  235. !   arcstream = 0;
  236.   
  237.     if (argc < 2)
  238.       usage ("too few command arguments", 0);
  239. ***************
  240. *** 359,365 ****
  241.           break;
  242.   
  243.         case 'r':
  244. !         if (operation)
  245.             two_operations ();
  246.           operation = REPLACE;
  247.           break;
  248. --- 444,450 ----
  249.           break;
  250.   
  251.         case 'r':
  252. !         if (operation && operation != REPLACE)
  253.             two_operations ();
  254.           operation = REPLACE;
  255.           break;
  256. ***************
  257. *** 375,380 ****
  258. --- 460,467 ----
  259.           break;
  260.   
  261.         case 'u':
  262. +         if (operation && operation != REPLACE)
  263. +           two_operations ();
  264.           operation = REPLACE;
  265.           newer_only = 1;
  266.           break;
  267. ***************
  268. *** 402,414 ****
  269.     i = 2;
  270.   
  271.     if (postype != POS_DEFAULT)
  272. !     posname = argv[i++];
  273.   
  274.     archive = argv[i++];
  275.   
  276.     if (i < argc)
  277.       {
  278. !       files = &argv[i];
  279.         while (i < argc)
  280.       if (!strcmp (argv[i++], "__.SYMDEF"))
  281.         {
  282. --- 489,501 ----
  283.     i = 2;
  284.   
  285.     if (postype != POS_DEFAULT)
  286. !     posname = make_file_args(&argv[i++], 1);
  287.   
  288.     archive = argv[i++];
  289.   
  290.     if (i < argc)
  291.       {
  292. !       file_args = make_file_args(&argv[i], argc - i);
  293.         while (i < argc)
  294.       if (!strcmp (argv[i++], "__.SYMDEF"))
  295.         {
  296. ***************
  297. *** 432,453 ****
  298.       break;
  299.   
  300.       case DELETE:
  301. !     if (files != 0)
  302.         delete_members ();
  303.       break;
  304.   
  305.       case MOVE:
  306. !     if (files != 0)
  307.         move_members ();
  308.       break;
  309.   
  310.       case REPLACE:
  311. !     if (files != 0 || symdef_flag)
  312.         replace_members ();
  313.       break;
  314.   
  315.       case QUICK_APPEND:
  316. !     if (files != 0)
  317.         quick_append ();
  318.       break;
  319.   
  320. --- 519,540 ----
  321.       break;
  322.   
  323.       case DELETE:
  324. !     if (file_args != 0)
  325.         delete_members ();
  326.       break;
  327.   
  328.       case MOVE:
  329. !     if (file_args != 0)
  330.         move_members ();
  331.       break;
  332.   
  333.       case REPLACE:
  334. !     if (file_args != 0 || symdef_flag)
  335.         replace_members ();
  336.       break;
  337.   
  338.       case QUICK_APPEND:
  339. !     if (file_args != 0)
  340.         quick_append ();
  341.       break;
  342.   
  343. ***************
  344. *** 465,476 ****
  345.     usage ("two different operation switches specified", 0);
  346.   }
  347.   
  348.   void
  349.   scan (function, crflag)
  350.        void (*function) ();
  351.        int crflag;
  352.   {
  353. !   FILE *arcstream = fopen (archive, "r");
  354.   
  355.     if (arcstream == 0 && crflag)
  356.       /* Creation-warning, if desired, will happen later.  */
  357. --- 552,566 ----
  358.     usage ("two different operation switches specified", 0);
  359.   }
  360.   
  361. + /* Apply the given function to all members in the archive.  */
  362.   void
  363.   scan (function, crflag)
  364.        void (*function) ();
  365.        int crflag;
  366.   {
  367. !   if (arcstream == 0)
  368. !     open_archive (O_RDONLY);
  369.   
  370.     if (arcstream == 0 && crflag)
  371.       /* Creation-warning, if desired, will happen later.  */
  372. ***************
  373. *** 477,492 ****
  374.       return;
  375.   
  376.     if (arcstream == 0)
  377. !     {
  378. !       perror_with_name (archive);
  379. !       exit (1);
  380. !     }
  381. !   {
  382. !     char buf[SARMAG];
  383. !     int nread = fread (buf, 1, SARMAG, arcstream);
  384. !     if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
  385. !       fatal ("file %s not a valid archive", archive);
  386. !   }
  387.   
  388.     /* Now find the members one by one.  */
  389.     {
  390. --- 567,574 ----
  391.       return;
  392.   
  393.     if (arcstream == 0)
  394. !     pfatal_with_name (archive);
  395. !   verify_is_archive (arcfd);
  396.   
  397.     /* Now find the members one by one.  */
  398.     {
  399. ***************
  400. *** 510,515 ****
  401. --- 592,599 ----
  402.           || bcmp (member_header.ar_fmag, ARFMAG, 2))
  403.         fatal ("file %s not a valid archive", archive);
  404.       bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
  405. +     /* remove trailing blanks */
  406.       {
  407.         char *p = name + sizeof member_header.ar_name;
  408.         *p = '\0';
  409. ***************
  410. *** 516,522 ****
  411.         while (p > name && *--p == ' ')
  412.           *p = '\0';
  413.       }
  414. !     member_desc.name = name;
  415.       sscanf (member_header.ar_mode, "%o", &member_desc.mode);
  416.       member_desc.date = atoi (member_header.ar_date);
  417.       member_desc.size = atoi (member_header.ar_size);
  418. --- 600,611 ----
  419.         while (p > name && *--p == ' ')
  420.           *p = '\0';
  421.       }
  422. !     /* Make a safe copy of the name, so that `function' can just 
  423. !        make a copy of `member_desc'.  */
  424. !     member_desc.name.stored = concat (name, "", "");
  425. !     member_desc.name.given = NULL;
  426.       sscanf (member_header.ar_mode, "%o", &member_desc.mode);
  427.       member_desc.date = atoi (member_header.ar_date);
  428.       member_desc.size = atoi (member_header.ar_size);
  429. ***************
  430. *** 540,548 ****
  431.         ++member_offset;
  432.         }
  433.     }
  434. -   
  435. -   fclose (arcstream);
  436.   }
  437.   
  438.   void print_modes ();
  439. --- 629,634 ----
  440. ***************
  441. *** 554,560 ****
  442.     char *timestring;
  443.     if (!verbose)
  444.       {
  445. !       puts (member.name);
  446.         return;
  447.       }
  448.     print_modes (member.mode);
  449. --- 640,646 ----
  450.     char *timestring;
  451.     if (!verbose)
  452.       {
  453. !       puts (member.name.stored);
  454.         return;
  455.       }
  456.     print_modes (member.mode);
  457. ***************
  458. *** 562,568 ****
  459.     printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
  460.         member.uid, member.gid,
  461.         member.size, timestring + 4, timestring + 20,
  462. !       member.name);
  463.   }
  464.   
  465.   void
  466. --- 648,654 ----
  467.     printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
  468.         member.uid, member.gid,
  469.         member.size, timestring + 4, timestring + 20,
  470. !       member.name.stored);
  471.   }
  472.   
  473.   void
  474. ***************
  475. *** 589,605 ****
  476.   {
  477.     int ncopied = 0;
  478.     FILE *ostream;
  479.   
  480.     fseek (istream, member.data_offset, 0);
  481. !   ostream = fopen (member.name, "w");
  482.     if (!ostream)
  483.       {
  484. !       perror_with_name (member.name);
  485.         return;
  486.       }
  487.   
  488.     if (verbose)
  489. !     printf ("x - %s\n", member.name);
  490.   
  491.     while (ncopied < member.size)
  492.       {
  493. --- 675,693 ----
  494.   {
  495.     int ncopied = 0;
  496.     FILE *ostream;
  497. +   char *filename;            /* name to store file into */
  498.   
  499.     fseek (istream, member.data_offset, 0);
  500. !   filename = (member.name.given ? member.name.given : member.name.stored);
  501. !   ostream = fopen (filename, "w");
  502.     if (!ostream)
  503.       {
  504. !       perror_with_name (filename);
  505.         return;
  506.       }
  507.   
  508.     if (verbose)
  509. !     printf ("x - %s\n", filename);
  510.   
  511.     while (ncopied < member.size)
  512.       {
  513. ***************
  514. *** 615,626 ****
  515.       }
  516.   
  517.   #ifdef USG
  518. !   chmod (member.name, member.mode);
  519.   #else
  520.     fchmod (fileno (ostream), member.mode);
  521.   #endif
  522.     if (ferror (ostream) || fclose (ostream) != 0)
  523. !     error ("%s: I/O error", member.name);
  524.   
  525.     if (preserve_dates)
  526.       {
  527. --- 703,714 ----
  528.       }
  529.   
  530.   #ifdef USG
  531. !   chmod (filename, member.mode);
  532.   #else
  533.     fchmod (fileno (ostream), member.mode);
  534.   #endif
  535.     if (ferror (ostream) || fclose (ostream) != 0)
  536. !     error ("%s: I/O error", filename);
  537.   
  538.     if (preserve_dates)
  539.       {
  540. ***************
  541. *** 628,634 ****
  542.         long tv[2];
  543.         tv[0] = member.date;
  544.         tv[1] = member.date;
  545. !       utime (member.name, tv);
  546.   #else
  547.         struct timeval tv[2];
  548.         tv[0].tv_sec = member.date;
  549. --- 716,722 ----
  550.         long tv[2];
  551.         tv[0] = member.date;
  552.         tv[1] = member.date;
  553. !       utime (filename, tv);
  554.   #else
  555.         struct timeval tv[2];
  556.         tv[0].tv_sec = member.date;
  557. ***************
  558. *** 635,641 ****
  559.         tv[0].tv_usec = 0;
  560.         tv[1].tv_sec = member.date;
  561.         tv[1].tv_usec = 0;
  562. !       utimes (member.name, tv);
  563.   #endif
  564.       }
  565.   }
  566. --- 723,729 ----
  567.         tv[0].tv_usec = 0;
  568.         tv[1].tv_sec = member.date;
  569.         tv[1].tv_usec = 0;
  570. !       utimes (filename, tv);
  571.   #endif
  572.       }
  573.   }
  574. ***************
  575. *** 650,656 ****
  576.     fseek (istream, member.data_offset, 0);
  577.   
  578.     if (verbose)
  579. !   printf ("\n<member %s>\n\n", member.name);
  580.   
  581.     while (ncopied < member.size)
  582.       {
  583. --- 738,744 ----
  584.     fseek (istream, member.data_offset, 0);
  585.   
  586.     if (verbose)
  587. !     printf ("\n<member %s>\n\n", member.name.stored);
  588.   
  589.     while (ncopied < member.size)
  590.       {
  591. ***************
  592. *** 690,697 ****
  593.        struct member_desc member;
  594.   {
  595.     struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  596.     mapelt->info = member;
  597. -   mapelt->info.name = concat (mapelt->info.name, "", "");
  598.     maplast->next = mapelt;
  599.     mapelt->next = 0;
  600.     maplast = mapelt;
  601. --- 778,785 ----
  602.        struct member_desc member;
  603.   {
  604.     struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  605.     mapelt->info = member;
  606.     maplast->next = mapelt;
  607.     mapelt->next = 0;
  608.     maplast = mapelt;
  609. ***************
  610. *** 721,756 ****
  611.     return 0;
  612.   }
  613.   
  614. ! /* Return the element of the specified map which has the specified name.  */
  615.   
  616.   struct mapelt *
  617.   find_mapelt_noerror (map, name)
  618.        struct mapelt *map;
  619. !      register char *name;
  620.   {
  621.     register struct mapelt *tail;
  622. -   unsigned int len = strlen (name);
  623. -   int dot_o = name[len - 2] == '.' && name[len - 1] == 'o';
  624.   
  625.     for (tail = map; tail != 0; tail = tail->next)
  626.       {
  627. !       if (tail->info.name == 0)
  628.       continue;
  629. !       if (!strncmp (tail->info.name, name, 13))
  630. !     {
  631. !       unsigned int eltlen = strlen (tail->info.name);
  632. !       if (len <= 13 || eltlen <= 13)
  633. !         return tail;
  634. !       else
  635. !         {
  636. !           char *p = tail->info.name + 13;
  637. !           if (dot_o && p[0] == '.' && p[1] == 'o' && p[2] == '\0')
  638. !         return tail;
  639. !           else if (!strncmp (p, name + 13,
  640. !                  (len > eltlen ? len : eltlen) - 13))
  641. !         return tail;
  642. !         }
  643. !     }
  644.       }
  645.   
  646.     return 0;
  647. --- 809,832 ----
  648.     return 0;
  649.   }
  650.   
  651. ! /* Return the element of the specified map which has the specified 
  652. !    name.  Possible side effect: if NAME or the matching element has a
  653. !    known `given' (user) name, that name is propagated so that both
  654. !    NAME and the matching element have it.  */
  655.   
  656.   struct mapelt *
  657.   find_mapelt_noerror (map, name)
  658.        struct mapelt *map;
  659. !      struct member_name *name;
  660.   {
  661.     register struct mapelt *tail;
  662.   
  663.     for (tail = map; tail != 0; tail = tail->next)
  664.       {
  665. !       if (marked_for_deletion (tail))
  666.       continue;
  667. !       if (name_match (&tail->info.name, name))
  668. !     return tail;
  669.       }
  670.   
  671.     return 0;
  672. ***************
  673. *** 759,878 ****
  674.   struct mapelt *
  675.   find_mapelt (map, name)
  676.        struct mapelt *map;
  677. !      char *name;
  678.   {
  679.     register struct mapelt *found = find_mapelt_noerror (map, name);
  680.     if (found == 0)
  681. !     error ("no member named `%s'", name);
  682.     return found;
  683.   }
  684.   
  685. ! /* Before looking at the archive, if we are going to update it
  686. !    based on looking at its current contents, make an exclusive lock on it.
  687. !    The lock is released when `write_archive' is called.  */
  688.   
  689.   void
  690. ! lock_for_update ()
  691. ! {
  692. !   /* Open the existing archive file; if that fails, create an empty one.  */
  693. !   lock_indesc = open (archive, O_RDWR, 0);
  694.   
  695. !   if (lock_indesc < 0)
  696. !     {
  697. !       int outdesc;
  698.   
  699.         if (!silent_create)
  700.       printf ("Creating archive file `%s'\n", archive);
  701. !       outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666);
  702. !       if (outdesc < 0)
  703. !     pfatal_with_name (archive);
  704. !       mywrite (outdesc, ARMAG, SARMAG, archive);
  705. !       close (outdesc);
  706.   
  707. !       /* Now we had better be able to open for update!  */
  708.   
  709. !       lock_indesc = open (archive, O_RDWR, 0);
  710. !       if (lock_indesc < 0)
  711. !     pfatal_with_name (archive);
  712. !     }
  713.   
  714. ! #ifdef LOCKS
  715. !   /* Lock the old file so that it won't be updated by two programs at once.
  716. !      This uses the fcntl locking facility found on Sun systems
  717. !      which is also in POSIX.  (Perhaps it comes from sysV.)
  718.   
  719. !      Note that merely reading an archive does not require a lock,
  720. !      because we use `rename' to update the whole file atomically.  */
  721.   
  722.     {
  723.       struct flock lock;
  724.   
  725. !     lock.l_type = F_WRLCK;
  726.       lock.l_whence = 0;
  727.       lock.l_start = 0;
  728.       lock.l_len = 0;
  729.   
  730. !     while (1)
  731. !       {
  732. !     int value = fcntl (lock_indesc, F_SETLKW, &lock);
  733. !     if (value >= 0)
  734. !       break;
  735. !     else if (errno == EINTR)
  736. !       continue;
  737. !     else
  738. !       pfatal_with_name ("locking archive");
  739. !       }
  740.     }
  741. ! #endif
  742.   }
  743.   
  744.   /* Unlock archive and close the file descriptor.  */
  745.   
  746.   void
  747.   close_archive ()
  748.   {
  749. ! #ifdef LOCKS
  750. !   {
  751. !     struct flock lock;
  752. !     /* Unlock the old archive.  */
  753. !     lock.l_type = F_UNLCK;
  754. !     lock.l_whence = 0;
  755. !     lock.l_start = 0;
  756. !     lock.l_len = 0;
  757. !     fcntl (lock_indesc, F_SETLK, &lock);
  758. !   }
  759.   #endif
  760.   
  761. !   /* Close the archive.  If we renamed a new one, the old one disappears.  */
  762. !   close (lock_indesc);
  763.   }
  764.   
  765.   /* Write a new archive file from a given map.  */
  766.   /* When a map is used as the pattern for a new archive,
  767. !  each element represents one member to put in it, and
  768. !  the order of elements controls the order of writing.
  769. !  Ordinarily, the element describes a member of the old
  770. !  archive, to be copied into the new one.
  771. !  If the `offset' field of the element's info is 0,
  772. !  then the element describes a file to be copied into the
  773. !  new archive.  The `name' field is the file's name.
  774. !  If the `name' field of an element is 0, the element is ignored.
  775. !  This makes it easy to specify deletion of archive members.
  776.   
  777. !  Every operation that will eventually call `write_archive'
  778. !  should call `lock_for_update' before beginning
  779. !  to do any I/O on the archive file.
  780.   */
  781.   
  782.   char *make_tempname ();
  783.   void copy_out_member ();
  784.   
  785.   void
  786.   write_archive (map, appendflag)
  787. --- 835,1093 ----
  788.   struct mapelt *
  789.   find_mapelt (map, name)
  790.        struct mapelt *map;
  791. !      struct member_name *name;
  792.   {
  793.     register struct mapelt *found = find_mapelt_noerror (map, name);
  794.     if (found == 0)
  795. !     error ("no member named `%s'", name->stored);
  796.     return found;
  797.   }
  798.   
  799. ! /* Open the archive, either read-only or read-write, using the global
  800. !    name "archive".  The archive is locked at this time to protect
  801. !    against a concurrent writer.  This lock will be released when the
  802. !    archive is closed.  This routine should only be called once--no
  803. !    upgrading of access from read-only to read-write is allowed.
  804. !    Side effects:
  805. !    - If opening read-write and the archive doesn't exist, create it.
  806. !    - arcfd and arctream are set to mean the opened archive.  If the
  807. !      archive doesn't exist and can't be created, they are left as
  808. !      meaning "unopened".  */
  809. ! void
  810. ! open_archive (how)
  811. !      int how;                /* O_RDONLY or O_RDWR */
  812. ! {
  813. !   void open_for_reading (), open_for_update ();
  814. !   if (arcfd != -1 || arcstream != 0)
  815. !     fatal ("opening archive twice");
  816. !   switch (how)
  817. !     {
  818. !     case O_RDONLY:
  819. !       open_for_reading ();
  820. !       break;
  821. !     case O_RDWR:
  822. !       open_for_update ();
  823. !       break;
  824. !     default:
  825. !       fatal ("bogus flag passed to open_archive");
  826. !     }
  827. ! }
  828. ! /* Open the archive for read-only access.  If the archive doesn't
  829. !    exist, just quit.  */
  830. ! void
  831. ! open_for_reading ()
  832. ! {
  833. !   arcfd = open (archive, O_RDONLY, 0);
  834. !   if (arcfd < 0 && errno != ENOENT)
  835. !     pfatal_with_name (archive);
  836. !   if (arcfd < 0)
  837. !     return;
  838. !   lock_a_file (arcfd, O_RDONLY);
  839.   
  840. +   arcstream = fdopen (arcfd, "r");
  841. +   if (arcstream == 0)
  842. +     fatal ("can't make stream for archive");
  843. + }
  844. + /* Open the archive for read-write access.  If it doesn't exist,
  845. +    create it.  The order of creates and opens and locks is to keep
  846. +    competing ar's (spawned by pmake) from tripping on each other.  */
  847.   void
  848. ! open_for_update ()
  849. ! {
  850. !   struct stat statbuf;
  851.   
  852. !   /* Assume that the archive doesn't exist, and try to create it.  If 
  853. !      it does exist, just open it normally.  */
  854. !   arcfd = open (archive, O_RDWR | O_CREAT | O_EXCL, 0666);
  855. !   if (arcfd < 0 && errno != EEXIST)
  856. !     pfatal_with_name (archive);
  857.   
  858. +   if (arcfd >= 0)
  859. +     {
  860.         if (!silent_create)
  861.       printf ("Creating archive file `%s'\n", archive);
  862. !     }
  863. !   else
  864. !     arcfd = open (archive, O_RDWR, 0);
  865.   
  866. !   /* If the file suddenly doesn't exist, punt.  Some user must have
  867. !      manually deleted the file.  */
  868. !   if (arcfd < 0)
  869. !     pfatal_with_name (archive);
  870. !   lock_a_file (arcfd, O_RDWR);
  871. !   /* Whew.  Now that we've got the file and it's locked, check whether
  872. !      it's really an archive or just an empty shell, created either by
  873. !      us or by a competing ar.  */
  874. !   fstat (arcfd, &statbuf);
  875. !   if (statbuf.st_size == 0)
  876. !     mywrite (arcfd, ARMAG, SARMAG, archive);
  877. !   else
  878. !     verify_is_archive (arcfd);
  879.   
  880. !   arcstream = fdopen (arcfd, "r+");
  881. !   if (arcstream == 0)
  882. !     fatal ("can't create stream for archive");
  883. ! }
  884.   
  885. ! #ifndef LOCKS
  886.   
  887. ! void
  888. ! lock_a_file (fd, how)
  889. !      int fd, how;
  890. ! {
  891. ! }
  892. ! void
  893. ! unlock_a_file (fd)
  894. !      int fd;
  895. ! {
  896. ! }
  897. ! #else /* LOCKS */
  898. ! /* Lock the old file so that it won't be written while there are
  899. !    readers or another writer.
  900. !    Non-sprite systems use the fcntl locking facility found on Sun
  901. !    systems, which is also in POSIX.  (Perhaps it comes from sysV.)  */
  902. ! #ifndef LOCK_FLOCK
  903. ! void
  904. ! lock_a_file (fd, how)
  905. !      int fd;
  906. !      int how;                /* read/write flag */
  907. ! {
  908. !   struct flock lock;
  909. !   lock.l_type = (how == O_RDONLY ? F_RDLCK : F_WRLCK);
  910. !   lock.l_whence = 0;
  911. !   lock.l_start = 0;
  912. !   lock.l_len = 0;
  913. !   while (1)
  914. !     {
  915. !       int value = fcntl (fd, F_SETLKW, &lock);
  916. !       if (value >= 0)
  917. !     break;
  918. !       else if (errno == EINTR)
  919. !     continue;
  920. !       else
  921. !     pfatal_with_name ("locking archive");
  922. !     }
  923. ! }
  924.   
  925. + void
  926. + unlock_a_file (fd)
  927. +      int fd;
  928.     {
  929.       struct flock lock;
  930.   
  931. !     /* Unlock the old archive.  */
  932. !     lock.l_type = F_UNLCK;
  933.       lock.l_whence = 0;
  934.       lock.l_start = 0;
  935.       lock.l_len = 0;
  936.   
  937. !     fcntl (fd, F_SETLK, &lock);
  938.     }
  939. ! #else /* LOCK_FLOCK */
  940. ! void
  941. ! lock_a_file (fd, how)
  942. !      int fd;
  943. !      int how;                /* read/write flag */
  944. ! {
  945. !   int lock_type = (how == O_RDONLY ? LOCK_SH : LOCK_EX);
  946. !   open_flags = how;
  947. !   if (flock (fd, lock_type) < 0)
  948. !     pfatal_with_name (archive);
  949. ! }
  950. ! /* Putting lock_flags in the flock() call is a workaround for a bug in 
  951. !    Sprite's flock() emulation.  -mdk 19-Oct-90 */
  952. ! void
  953. ! unlock_a_file (fd)
  954. !      int fd;
  955. ! {
  956. !   int lock_type = (open_flags == O_RDONLY ? LOCK_SH : LOCK_EX);
  957. !   if (flock (fd, LOCK_UN | lock_type) < 0)
  958. !     pfatal_with_name (archive);
  959.   }
  960.   
  961. + #endif /* LOCK_FLOCK */
  962. + #endif /* LOCKS */
  963.   /* Unlock archive and close the file descriptor.  */
  964.   
  965.   void
  966.   close_archive ()
  967.   {
  968. ! #ifndef USG
  969. !   fsync (arcfd);
  970.   #endif
  971. +   unlock_a_file (arcfd);
  972. +   if (close (arcfd) < 0)
  973. +     {
  974. +       perror_with_name (archive);
  975. +       exit (1);
  976. +     }
  977. + }
  978. + /* Ensure that the given file is an archive.  Side effect: repositions
  979. +    the archive.  After calling this routine, you should do a seek.  */
  980.   
  981. ! void
  982. ! verify_is_archive (fd)
  983. !      int fd;
  984. ! {
  985. !   char buf[SARMAG];
  986. !   int nread;
  987. !   lseek (fd, 0, L_SET);
  988. !   nread = read (fd, buf, sizeof (buf));
  989. !   if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG) != 0)
  990. !     fatal ("file %s not a valid archive", archive);
  991.   }
  992.   
  993.   /* Write a new archive file from a given map.  */
  994.   /* When a map is used as the pattern for a new archive,
  995. !    each element represents one member to put in it, and
  996. !    the order of elements controls the order of writing.
  997. !   
  998. !    Ordinarily, the element describes a member of the old
  999. !    archive, to be copied into the new one.
  1000. !   
  1001. !    If, however, the `offset' field of the element's info is 0,
  1002. !    then the element describes a file to be copied into the
  1003. !    new archive.
  1004.   
  1005. !    The archive is updated by writing a new file and then copying the
  1006. !    new file onto the old one.  We don't use rename, because if some
  1007. !    other "ar" has the archive open and is waiting to obtain the lock,
  1008. !    it would end up with the old file, not the new one.  There can
  1009. !    never be two ar's writing the new file simultaneously, because of
  1010. !    the lock on the archive.
  1011.   */
  1012.   
  1013.   char *make_tempname ();
  1014.   void copy_out_member ();
  1015. + void copy_file ();
  1016.   
  1017.   void
  1018.   write_archive (map, appendflag)
  1019. ***************
  1020. *** 880,900 ****
  1021.        int appendflag;
  1022.   {
  1023.     char *tempname = make_tempname (archive);
  1024. !   int indesc = lock_indesc;
  1025.     int outdesc;
  1026.     char *outname;
  1027.     struct mapelt *tail;
  1028.   
  1029.     /* Now open the output.  */
  1030.   
  1031.     if (!appendflag)
  1032.       {
  1033. !       /* Updating an existing archive normally.
  1034. !      Write output as TEMPNAME and rename at the end.
  1035. !      There can never be two invocations trying to do this at once,
  1036. !      because of the lock made on the old archive file.  */
  1037.   
  1038. !       outdesc = open (tempname, O_WRONLY | O_CREAT, 0666);
  1039.         if (outdesc < 0)
  1040.       pfatal_with_name (tempname);
  1041.         outname = tempname;
  1042. --- 1095,1117 ----
  1043.        int appendflag;
  1044.   {
  1045.     char *tempname = make_tempname (archive);
  1046. !   int indesc = arcfd;
  1047.     int outdesc;
  1048.     char *outname;
  1049.     struct mapelt *tail;
  1050.   
  1051. +   /* Sanity check */
  1052. +   if (open_flags == O_RDONLY)
  1053. +     fatal ("want to update archive after declaring read-only");
  1054.     /* Now open the output.  */
  1055.   
  1056.     if (!appendflag)
  1057.       {
  1058. !       /* Write the revised archive to TEMPNAME, then copy it back. */
  1059.   
  1060. !       outdesc = open (tempname, O_RDWR | O_CREAT, 0666);
  1061.         if (outdesc < 0)
  1062.       pfatal_with_name (tempname);
  1063.         outname = tempname;
  1064. ***************
  1065. *** 921,927 ****
  1066.       {
  1067.         struct mapelt *this = (struct mapelt *)
  1068.           xmalloc (sizeof (struct mapelt));
  1069. !       this->info.name = "__.SYMDEF";
  1070.         this->info.offset = SARMAG;
  1071.         this->info.data_offset = SARMAG + sizeof (struct ar_hdr);
  1072.         this->info.new_offset = 0;
  1073. --- 1138,1144 ----
  1074.       {
  1075.         struct mapelt *this = (struct mapelt *)
  1076.           xmalloc (sizeof (struct mapelt));
  1077. !       init_name (&this->info.name, "__.SYMDEF");
  1078.         this->info.offset = SARMAG;
  1079.         this->info.data_offset = SARMAG + sizeof (struct ar_hdr);
  1080.         this->info.new_offset = 0;
  1081. ***************
  1082. *** 947,954 ****
  1083.   
  1084.     for (tail = map; tail != 0; tail = tail->next)
  1085.       {
  1086. !       if ((symdef_flag || symdef_exists) && tail->info.name
  1087. !       && !strcmp (tail->info.name, "__.SYMDEF")
  1088.   #if 0
  1089.         && tail->info.date==0
  1090.   #endif
  1091. --- 1164,1171 ----
  1092.   
  1093.     for (tail = map; tail != 0; tail = tail->next)
  1094.       {
  1095. !       if ((symdef_flag || symdef_exists) && !marked_for_deletion(tail)
  1096. !       && name_match (&tail->info.name, &symdef_name)
  1097.   #if 0
  1098.         && tail->info.date==0
  1099.   #endif
  1100. ***************
  1101. *** 985,1028 ****
  1102.     if (symdef_mapelt != 0)
  1103.       touch_symdef_member (outdesc, outname);
  1104.   
  1105. !   /* Install the new output under the intended name.  */
  1106. ! #ifndef USG
  1107. !   fsync (outdesc);
  1108. ! #endif
  1109.     close (outdesc);
  1110.     if (!appendflag)
  1111. !     if (rename (tempname, archive))
  1112. !       pfatal_with_name (tempname);
  1113.   
  1114.     close_archive ();
  1115.   }
  1116.   
  1117.   void
  1118.   header_from_map (header, mapelt)
  1119.        struct ar_hdr *header;
  1120.        struct mapelt *mapelt;
  1121.   {
  1122. -   unsigned int namelen;
  1123.     /* Zero the header, then store in the data as text.  */
  1124.     bzero ((char *) header, sizeof (*header));
  1125.   
  1126. !   strncpy (header->ar_name, mapelt->info.name, sizeof (header->ar_name));
  1127. !   namelen = strlen (mapelt->info.name);
  1128. !   if (namelen >= sizeof (header->ar_name))
  1129. !     {
  1130. !       if (mapelt->info.name[namelen - 2] == '.' &&
  1131. !       mapelt->info.name[namelen - 1] == 'o')
  1132. !     {
  1133. !       header->ar_name[sizeof (header->ar_name) - 3] = '.';
  1134. !       header->ar_name[sizeof (header->ar_name) - 2] = 'o';
  1135. !     }
  1136. !       header->ar_name[sizeof (header->ar_name) - 1] = '\0';
  1137. !       error ("member name `%s' truncated to `%s'",
  1138. !          mapelt->info.name, header->ar_name);
  1139. !     }
  1140.   
  1141.     sprintf (header->ar_date, "%ld", mapelt->info.date);
  1142.     sprintf (header->ar_size, "%d", mapelt->info.size);
  1143. --- 1202,1254 ----
  1144.     if (symdef_mapelt != 0)
  1145.       touch_symdef_member (outdesc, outname);
  1146.   
  1147. !   if (!appendflag)
  1148. !     copy_file (outdesc, tempname, arcfd, archive);
  1149.     close (outdesc);
  1150.     if (!appendflag)
  1151. !     unlink (tempname);
  1152.   
  1153.     close_archive ();
  1154.   }
  1155.   
  1156. + /* Copy all of fromfd to tofd.  The file names are passed in for error
  1157. +    reporting.  */
  1158. + void
  1159. + copy_file (from_fd, from_name, to_fd, to_name)
  1160. +      int from_fd, to_fd;
  1161. +      char *from_name, *to_name;
  1162. + {
  1163. +   char buf[8192];
  1164. +   int nchars;
  1165. +   lseek (from_fd, 0, L_SET);
  1166. +   lseek (to_fd, 0, L_SET);
  1167. +   if (ftruncate (to_fd, 0) < 0)
  1168. +     pfatal_with_name (to_name);
  1169. +   while ((nchars = read (from_fd, buf, sizeof (buf))) > 0)
  1170. +     {
  1171. +       if (write (to_fd, buf, nchars) != nchars) 
  1172. +     pfatal_with_name (to_name);
  1173. +     }
  1174. +   if (nchars < 0)
  1175. +     pfatal_with_name (from_name);
  1176. + }
  1177. + /* Fill in an ar header for an element of the archive.  */
  1178.   void
  1179.   header_from_map (header, mapelt)
  1180.        struct ar_hdr *header;
  1181.        struct mapelt *mapelt;
  1182.   {
  1183.     /* Zero the header, then store in the data as text.  */
  1184.     bzero ((char *) header, sizeof (*header));
  1185.   
  1186. !   assert (mapelt->info.name.stored != NULL);
  1187. !   assert (strlen (mapelt->info.name.stored) < sizeof (header->ar_name));
  1188. !   strcpy (header->ar_name, mapelt->info.name.stored);
  1189.   
  1190.     sprintf (header->ar_date, "%ld", mapelt->info.date);
  1191.     sprintf (header->ar_size, "%d", mapelt->info.size);
  1192. ***************
  1193. *** 1047,1062 ****
  1194.        struct mapelt *mapelt;
  1195.        int archive_indesc;
  1196.        int outdesc;
  1197.   {
  1198.     struct ar_hdr header;
  1199.     int indesc;
  1200.   
  1201. !   if (mapelt->info.name == 0)
  1202. !     /* This element was cancelled.  */
  1203.       return;
  1204.   
  1205.     header_from_map (&header, mapelt);
  1206.   
  1207.     if (mapelt->info.offset != 0)
  1208.       {
  1209.         indesc = archive_indesc;
  1210. --- 1273,1290 ----
  1211.        struct mapelt *mapelt;
  1212.        int archive_indesc;
  1213.        int outdesc;
  1214. +      char *outname;
  1215.   {
  1216.     struct ar_hdr header;
  1217.     int indesc;
  1218.   
  1219. !   if (marked_for_deletion (mapelt))
  1220.       return;
  1221.   
  1222.     header_from_map (&header, mapelt);
  1223.   
  1224. +   /* Either copy the member from the (old) archive, or copy it from 
  1225. +      the user-named filed.  */
  1226.     if (mapelt->info.offset != 0)
  1227.       {
  1228.         indesc = archive_indesc;
  1229. ***************
  1230. *** 1064,1073 ****
  1231.       }
  1232.     else
  1233.       {
  1234. !       indesc = open (mapelt->info.name, 0, 0);
  1235.         if (indesc < 0)
  1236.       {
  1237. !       perror_with_name (mapelt->info.name);
  1238.         return;
  1239.       }
  1240.       }
  1241. --- 1292,1302 ----
  1242.       }
  1243.     else
  1244.       {
  1245. !       assert (mapelt->info.name.given != NULL);
  1246. !       indesc = open (mapelt->info.name.given, O_RDONLY, 0);
  1247.         if (indesc < 0)
  1248.       {
  1249. !       perror_with_name (mapelt->info.name.given);
  1250.         return;
  1251.       }
  1252.       }
  1253. ***************
  1254. *** 1134,1158 ****
  1255.   void
  1256.   delete_members ()
  1257.   {
  1258. !   struct mapelt *map = make_map (0);
  1259. !   struct mapelt *tail;
  1260.     struct mapelt mapstart;
  1261. !   char **p;
  1262.   
  1263. !   mapstart.info.name = 0;
  1264.     mapstart.next = map;
  1265.     map = &mapstart;
  1266.   
  1267. !   lock_for_update ();
  1268. !   if (files)
  1269. !     for (p = files; *p; p++)
  1270.         {
  1271.       /* If user says to delete the __.SYMDEF member,
  1272.          don't make a new one to replace it.  */
  1273. !     if (!strcmp (*p, "__.SYMDEF"))
  1274.         symdef_exists = 0;
  1275. !     delete_from_map (*p, map);
  1276.         }
  1277.   
  1278.     write_archive (map->next, 0);
  1279. --- 1363,1387 ----
  1280.   void
  1281.   delete_members ()
  1282.   {
  1283. !   struct mapelt *map;
  1284.     struct mapelt mapstart;
  1285. !   struct member_name *name;
  1286.   
  1287. !   open_archive (O_RDWR);
  1288. !   map = make_map (0);
  1289. !   init_elt (&mapstart);
  1290.     mapstart.next = map;
  1291.     map = &mapstart;
  1292.   
  1293. !   if (file_args)
  1294. !     for (name = file_args; !Empty_Name(name); name++)
  1295.         {
  1296.       /* If user says to delete the __.SYMDEF member,
  1297.          don't make a new one to replace it.  */
  1298. !     if (name_match (name, &symdef_name))
  1299.         symdef_exists = 0;
  1300. !     delete_from_map (name, map);
  1301.         }
  1302.   
  1303.     write_archive (map->next, 0);
  1304. ***************
  1305. *** 1160,1191 ****
  1306.   
  1307.   void
  1308.   delete_from_map (name, map)
  1309. !      char *name;
  1310.        struct mapelt *map;
  1311.   {
  1312.     struct mapelt *this = find_mapelt (map, name);
  1313.   
  1314.     if (!this) return;
  1315. !   this->info.name = 0;
  1316.     if (verbose)
  1317. !     printf ("d - %s\n", name);
  1318.   }
  1319.   
  1320.   void
  1321.   move_members ()
  1322.   {
  1323. !   struct mapelt *map = make_map (0);
  1324. !   char **p;
  1325.     struct mapelt *after_mapelt;
  1326.     struct mapelt mapstart;
  1327.     struct mapelt *change_map;
  1328.   
  1329. !   mapstart.info.name = 0;
  1330.     mapstart.next = map;
  1331.     change_map = &mapstart;
  1332.   
  1333. -   lock_for_update ();
  1334.     switch (postype)
  1335.       {
  1336.       case POS_DEFAULT:
  1337. --- 1389,1421 ----
  1338.   
  1339.   void
  1340.   delete_from_map (name, map)
  1341. !      struct member_name *name;
  1342.        struct mapelt *map;
  1343.   {
  1344.     struct mapelt *this = find_mapelt (map, name);
  1345.   
  1346.     if (!this) return;
  1347. !   mark_as_deleted (this);
  1348.     if (verbose)
  1349. !     printf ("d - %s\n", name->stored);
  1350.   }
  1351.   
  1352.   void
  1353.   move_members ()
  1354.   {
  1355. !   struct mapelt *map;
  1356. !   struct member_name *name;
  1357.     struct mapelt *after_mapelt;
  1358.     struct mapelt mapstart;
  1359.     struct mapelt *change_map;
  1360.   
  1361. !   open_archive (O_RDWR);
  1362. !   map = make_map (0);
  1363. !   init_elt (&mapstart);
  1364.     mapstart.next = map;
  1365.     change_map = &mapstart;
  1366.   
  1367.     switch (postype)
  1368.       {
  1369.       case POS_DEFAULT:
  1370. ***************
  1371. *** 1197,1203 ****
  1372.         break;
  1373.   
  1374.       case POS_BEFORE:
  1375. !       after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  1376.       }
  1377.   
  1378.     /* Failure to find specified "before" or "after" member
  1379. --- 1427,1439 ----
  1380.         break;
  1381.   
  1382.       case POS_BEFORE:
  1383. !       after_mapelt = prev_mapelt (change_map, find_mapelt (map,
  1384. !                                posname));
  1385. !       break;
  1386. !     default:
  1387. !       after_mapelt = 0;            /* lint */
  1388. !       fatal ("bogus position type");    /* "can't happen" */
  1389.       }
  1390.   
  1391.     /* Failure to find specified "before" or "after" member
  1392. ***************
  1393. *** 1205,1230 ****
  1394.   
  1395.     if (!after_mapelt) exit (1);
  1396.   
  1397. !   if (files)
  1398. !     for (p = files; *p; p++)
  1399.         {
  1400. !     if (move_in_map (*p, change_map, after_mapelt))
  1401.         after_mapelt = after_mapelt->next;
  1402.         }
  1403.   
  1404. !   write_archive (map, 0);
  1405.   }
  1406.   
  1407.   int
  1408.   move_in_map (name, map, after)
  1409. !      char *name;
  1410.        struct mapelt *map, *after;
  1411.   {
  1412.     struct mapelt *this = find_mapelt (map, name);
  1413.     struct mapelt *prev;
  1414.   
  1415. !   if (!this) return 0;
  1416.     prev = prev_mapelt (map, this);
  1417.     prev->next = this->next;
  1418.     this->next = after->next;
  1419.     after->next = this;
  1420. --- 1441,1469 ----
  1421.   
  1422.     if (!after_mapelt) exit (1);
  1423.   
  1424. !   if (file_args)
  1425. !     for (name = file_args; !Empty_Name(name); name++)
  1426.         {
  1427. !     if (move_in_map (name, change_map, after_mapelt))
  1428.         after_mapelt = after_mapelt->next;
  1429.         }
  1430.   
  1431. !   write_archive (change_map->next, 0);
  1432.   }
  1433.   
  1434.   int
  1435.   move_in_map (name, map, after)
  1436. !      struct member_name *name;
  1437.        struct mapelt *map, *after;
  1438.   {
  1439.     struct mapelt *this = find_mapelt (map, name);
  1440.     struct mapelt *prev;
  1441.   
  1442. !   if (!this)
  1443. !     return 0;
  1444.     prev = prev_mapelt (map, this);
  1445. +   if (this == after || prev == after)
  1446. +     return 1;                /* no-op */
  1447.     prev->next = this->next;
  1448.     this->next = after->next;
  1449.     after->next = this;
  1450. ***************
  1451. *** 1236,1254 ****
  1452.   void
  1453.   replace_members ()
  1454.   {
  1455. !   struct mapelt *map = make_map (1);
  1456.     struct mapelt mapstart;
  1457.     struct mapelt *after_mapelt;
  1458.     struct mapelt *change_map;
  1459. !   char **p;
  1460.     int changed;
  1461.   
  1462. !   mapstart.info.name = 0;
  1463.     mapstart.next = map;
  1464.     change_map = &mapstart;
  1465.   
  1466. -   lock_for_update ();
  1467.     switch (postype)
  1468.       {
  1469.       case POS_DEFAULT:
  1470. --- 1475,1494 ----
  1471.   void
  1472.   replace_members ()
  1473.   {
  1474. !   struct mapelt *map;
  1475.     struct mapelt mapstart;
  1476.     struct mapelt *after_mapelt;
  1477.     struct mapelt *change_map;
  1478. !   struct member_name *name;
  1479.     int changed;
  1480.   
  1481. !   open_archive (O_RDWR);
  1482. !   map = make_map (1);
  1483. !   init_elt (&mapstart);
  1484.     mapstart.next = map;
  1485.     change_map = &mapstart;
  1486.   
  1487.     switch (postype)
  1488.       {
  1489.       case POS_DEFAULT:
  1490. ***************
  1491. *** 1261,1266 ****
  1492. --- 1501,1511 ----
  1493.   
  1494.       case POS_BEFORE:
  1495.         after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  1496. +       break;
  1497. +     default:
  1498. +       after_mapelt = 0;            /* lint */
  1499. +       fatal ("bogus position type");    /* "can't happen" */
  1500.       }
  1501.   
  1502.     /* Failure to find specified "before" or "after" member
  1503. ***************
  1504. *** 1269,1288 ****
  1505.       exit (1);
  1506.   
  1507.     changed = 0;
  1508. !   if (files != 0)
  1509. !     for (p = files; *p != 0; ++p)
  1510. !       if (insert_in_map (*p, change_map, after_mapelt))
  1511.       {
  1512.         after_mapelt = after_mapelt->next;
  1513.         changed = 1;
  1514.       }
  1515.   
  1516. -   change_map = change_map->next;
  1517.     if (!changed && (!symdef_flag || symdef_exists))
  1518.       /* Nothing changed.  */
  1519. !     close_archive (change_map);
  1520.     else
  1521. !     write_archive (change_map, 0);
  1522.   }
  1523.   
  1524.   /* Handle the "quick insert" operation.  */
  1525. --- 1514,1532 ----
  1526.       exit (1);
  1527.   
  1528.     changed = 0;
  1529. !   if (file_args)
  1530. !     for (name = file_args; !Empty_Name(name); ++name)
  1531. !       if (insert_in_map (name, change_map, after_mapelt))
  1532.       {
  1533.         after_mapelt = after_mapelt->next;
  1534.         changed = 1;
  1535.       }
  1536.   
  1537.     if (!changed && (!symdef_flag || symdef_exists))
  1538.       /* Nothing changed.  */
  1539. !     close_archive ();
  1540.     else
  1541. !     write_archive (change_map->next, 0);
  1542.   }
  1543.   
  1544.   /* Handle the "quick insert" operation.  */
  1545. ***************
  1546. *** 1293,1314 ****
  1547.     struct mapelt *map;
  1548.     struct mapelt *after;
  1549.     struct mapelt mapstart;
  1550. !   char **p;
  1551.   
  1552. !   mapstart.info.name = 0;
  1553.     mapstart.next = 0;
  1554.     map = &mapstart;
  1555.     after = map;
  1556.   
  1557. !   lock_for_update ();
  1558.   
  1559.     /* Insert the specified files into the "map",
  1560.        but is a map of the inserted files only,
  1561.        and starts out empty.  */
  1562. !   if (files)
  1563. !     for (p = files; *p; p++)
  1564.         {
  1565. !     if (insert_in_map (*p, map, after))
  1566.         after = after->next;
  1567.         }
  1568.   
  1569. --- 1537,1558 ----
  1570.     struct mapelt *map;
  1571.     struct mapelt *after;
  1572.     struct mapelt mapstart;
  1573. !   struct member_name *name;
  1574.   
  1575. !   init_elt (&mapstart);
  1576.     mapstart.next = 0;
  1577.     map = &mapstart;
  1578.     after = map;
  1579.   
  1580. !   open_archive (O_RDWR);
  1581.   
  1582.     /* Insert the specified files into the "map",
  1583.        but is a map of the inserted files only,
  1584.        and starts out empty.  */
  1585. !   if (file_args)
  1586. !     for (name = file_args; !Empty_Name(name); name++)
  1587.         {
  1588. !     if (insert_in_map (name, map, after))
  1589.         after = after->next;
  1590.         }
  1591.   
  1592. ***************
  1593. *** 1317,1350 ****
  1594.     write_archive (map->next, 1);
  1595.   }
  1596.   
  1597. ! /* Insert an entry for name NAME into the map MAP after the map entry AFTER.
  1598. !    Delete an old entry for NAME.
  1599.      MAP is assumed to start with a dummy entry, which facilitates
  1600.      insertion at the beginning of the list.
  1601. !    Return 1 if successful, 0 if did nothing because file NAME doesn't
  1602. !    exist or (optionally) is older.  */
  1603.   
  1604.   int
  1605. ! insert_in_map (name, map, after)
  1606. !      char *name;
  1607.        struct mapelt *map, *after;
  1608.   {
  1609. !   struct mapelt *old = find_mapelt_noerror (map, name);
  1610.     struct mapelt *this;
  1611.     struct stat status;
  1612.   
  1613. !   if (stat (name, &status))
  1614.       {
  1615. !       perror_with_name (name);
  1616.         return 0;
  1617.       }
  1618.     if (old && newer_only && status.st_mtime <= old->info.date)
  1619.       return 0;
  1620. !   if (old)
  1621. !     /* Delete the old one.  */
  1622. !     old->info.name = 0;
  1623.     this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  1624. !   this->info.name = name;
  1625.     this->info.offset = 0;
  1626.     this->info.data_offset = 0;
  1627.     this->info.date = status.st_mtime;
  1628. --- 1561,1597 ----
  1629.     write_archive (map->next, 1);
  1630.   }
  1631.   
  1632. ! /* Insert an entry for REQUESTED_NAME into the map MAP after the map
  1633. !    entry AFTER. 
  1634. !    Deletes any old entry for REQUESTED_NAME.
  1635.      MAP is assumed to start with a dummy entry, which facilitates
  1636.      insertion at the beginning of the list.
  1637. !    Return 1 if successful, 0 if did nothing because file
  1638. !    REQUESTED_NAME doesn't exist or (optionally) is older.  */
  1639.   
  1640.   int
  1641. ! insert_in_map (requested_name, map, after)
  1642. !      struct member_name *requested_name;
  1643.        struct mapelt *map, *after;
  1644.   {
  1645. !   struct mapelt *old = find_mapelt_noerror (map, requested_name);
  1646.     struct mapelt *this;
  1647.     struct stat status;
  1648.   
  1649. !   assert (requested_name->given != NULL);
  1650. !   if (stat (requested_name->given, &status))
  1651.       {
  1652. !       perror_with_name (requested_name->given);
  1653.         return 0;
  1654.       }
  1655.     if (old && newer_only && status.st_mtime <= old->info.date)
  1656.       return 0;
  1657.     this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  1658. !   if (old)
  1659. !     mark_as_deleted (old);
  1660. !   this->info.name = *requested_name;
  1661.     this->info.offset = 0;
  1662.     this->info.data_offset = 0;
  1663.     this->info.date = status.st_mtime;
  1664. ***************
  1665. *** 1356,1362 ****
  1666.     after->next = this;
  1667.   
  1668.     if (verbose)
  1669. !     printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name);
  1670.   
  1671.     return 1;
  1672.   }
  1673. --- 1603,1609 ----
  1674.     after->next = this;
  1675.   
  1676.     if (verbose)
  1677. !     printf ("%c - %s\n", old == 0 ? 'a' : 'r', this->info.name.stored);
  1678.   
  1679.     return 1;
  1680.   }
  1681. ***************
  1682. *** 1369,1378 ****
  1683.        void (*function) ();
  1684.   {
  1685.     struct mapelt *map;
  1686. !   FILE *arcstream;
  1687. !   char **p;
  1688.   
  1689. !   if (!files)
  1690.       {
  1691.         /* Handle case where we want to operate on every member.
  1692.        No need to make a map and search it for this.  */
  1693. --- 1616,1624 ----
  1694.        void (*function) ();
  1695.   {
  1696.     struct mapelt *map;
  1697. !   struct member_name *name;
  1698.   
  1699. !   if (!file_args)
  1700.       {
  1701.         /* Handle case where we want to operate on every member.
  1702.        No need to make a map and search it for this.  */
  1703. ***************
  1704. *** 1380,1398 ****
  1705.         return;
  1706.       }
  1707.   
  1708. !   arcstream = fopen (archive, "r");
  1709. !   if (!arcstream)
  1710.       fatal ("failure opening archive %s for the second time", archive);
  1711.     map = make_map (0);
  1712.   
  1713. !   for (p = files; *p; p++)
  1714.       {
  1715. !       struct mapelt *this = find_mapelt (map, *p);
  1716.         if (!this) continue;
  1717.         function (this->info, arcstream);
  1718.       }
  1719. -   fclose (arcstream);
  1720.   }
  1721.   
  1722.   /* Write the __.SYMDEF member from data in core.  OUTDESC and OUTNAME
  1723. --- 1626,1644 ----
  1724.         return;
  1725.       }
  1726.   
  1727. !   if (arcstream == 0)
  1728. !     open_archive (O_RDONLY);
  1729. !   if (arcstream == 0)
  1730.       fatal ("failure opening archive %s for the second time", archive);
  1731. +   verify_is_archive (arcfd);
  1732.     map = make_map (0);
  1733.   
  1734. !   for (name = file_args; !Empty_Name(name); name++)
  1735.       {
  1736. !       struct mapelt *this = find_mapelt (map, name);
  1737.         if (!this) continue;
  1738.         function (this->info, arcstream);
  1739.       }
  1740.   }
  1741.   
  1742.   /* Write the __.SYMDEF member from data in core.  OUTDESC and OUTNAME
  1743. ***************
  1744. *** 1406,1417 ****
  1745.        char *outname;
  1746.   {
  1747.     struct ar_hdr header;
  1748. -   int indesc;
  1749.     struct mapelt *mapptr;
  1750.     unsigned long int symdefs_size;
  1751.   
  1752. !   if (mapelt->info.name == 0)
  1753. !     /* This element was cancelled.  */
  1754.       return;
  1755.   
  1756.     header_from_map (&header, mapelt);
  1757. --- 1652,1662 ----
  1758.        char *outname;
  1759.   {
  1760.     struct ar_hdr header;
  1761.     struct mapelt *mapptr;
  1762.     unsigned long int symdefs_size;
  1763. +   int symdef_sanity_count;
  1764.   
  1765. !   if (marked_for_deletion (mapelt))
  1766.       return;
  1767.   
  1768.     header_from_map (&header, mapelt);
  1769. ***************
  1770. *** 1420,1426 ****
  1771.   
  1772.     mywrite (outdesc, &header, sizeof (header), outname);
  1773.   
  1774. !   /* Write the number of symdefs.  */
  1775.     symdefs_size = nsymdefs * sizeof (struct symdef);
  1776.     mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname);
  1777.   
  1778. --- 1665,1671 ----
  1779.   
  1780.     mywrite (outdesc, &header, sizeof (header), outname);
  1781.   
  1782. !   /* Write the number of bytes taken by the symdef table.  */
  1783.     symdefs_size = nsymdefs * sizeof (struct symdef);
  1784.     mywrite (outdesc, &symdefs_size, sizeof symdefs_size, outname);
  1785.   
  1786. ***************
  1787. *** 1427,1439 ****
  1788.     /* Write symdefs surviving from old archive.  */
  1789.     mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef),
  1790.          outname);
  1791.   
  1792.     /* Write symdefs for new members.  */
  1793.     for (mapptr = map; mapptr != 0; mapptr = mapptr->next)
  1794.       if (mapptr->info.nsymdefs != 0)
  1795. !       write (outdesc, mapptr->info.symdefs,
  1796. !          mapptr->info.nsymdefs * sizeof (struct symdef));
  1797.   
  1798.     /* Write the string table size.  */
  1799.     mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname);
  1800.   
  1801. --- 1672,1699 ----
  1802.     /* Write symdefs surviving from old archive.  */
  1803.     mywrite (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef),
  1804.          outname);
  1805. +   symdef_sanity_count = num_old_symdefs;
  1806. + #if DEBUG
  1807. +   verify_symdefs (map, old_symdefs, num_old_symdefs, new_strings);
  1808. + #endif
  1809.   
  1810.     /* Write symdefs for new members.  */
  1811.     for (mapptr = map; mapptr != 0; mapptr = mapptr->next)
  1812.       if (mapptr->info.nsymdefs != 0)
  1813. !       {
  1814. !     write (outdesc, mapptr->info.symdefs,
  1815. !            mapptr->info.nsymdefs * sizeof (struct symdef));
  1816. ! #if DEBUG
  1817. !     verify_symdefs (map, mapptr->info.symdefs, mapptr->info.nsymdefs,
  1818. !             new_strings);
  1819. ! #endif
  1820. !     symdef_sanity_count += mapptr->info.nsymdefs;
  1821. !       }
  1822.   
  1823. +   if (symdef_sanity_count != nsymdefs)
  1824. +     fatal ("bug: wrote wrong number of symdefs");
  1825.     /* Write the string table size.  */
  1826.     mywrite (outdesc, &new_strings_size, sizeof new_strings_size, outname);
  1827.   
  1828. ***************
  1829. *** 1444,1449 ****
  1830. --- 1704,1764 ----
  1831.       mywrite (outdesc, "", 1, outname);
  1832.   }
  1833.   
  1834. + #if DEBUG
  1835. + /* Verify that the given symdefs point to the right place.  Treat the
  1836. +    symbol as the name of a .o file and look it up.  If we find it,
  1837. +    make sure we are pointing to it and not to some other .o file.  */
  1838. + void
  1839. + verify_symdefs (map, symdefs, numsymdefs, string_table)
  1840. +      struct mapelt *map;
  1841. +      struct symdef *symdefs;
  1842. +      unsigned int numsymdefs;
  1843. +      char *string_table;
  1844. + {
  1845. +   struct symdef *sym;
  1846. +   struct member_name file_name;
  1847. +   struct mapelt *member;
  1848. +   char *tmp_name;
  1849. +   for (sym = symdefs; sym < symdefs+numsymdefs; ++sym)
  1850. +     {
  1851. +       tmp_name = concat (string_table + sym->s.stringoffset, ".o", "");
  1852. +       init_name (&file_name, (tmp_name[0] == '_' ? tmp_name+1 : tmp_name));
  1853. +       member = find_mapelt_noerror (map, &file_name);
  1854. +       if (member)
  1855. +     {
  1856. +       if (member->info.new_offset)
  1857. +         {
  1858. +           if (member->info.new_offset != sym->offset)
  1859. +         {
  1860. +           printf ("Symbol %s points to 0x%x, which doesn't match \
  1861. + 0x%x (old 0x%x)\n",
  1862. +               string_table + sym->s.stringoffset,
  1863. +               sym->offset,
  1864. +               member->info.new_offset,
  1865. +               member->info.offset);
  1866. +           abort ();
  1867. +         }
  1868. +         }
  1869. +       /* else no new offset, so check the old one */
  1870. +       else if (member->info.offset != sym->offset)
  1871. +         {
  1872. +           printf ("Symbol %s points to 0x%x, which doesn't match 0x%x\n",
  1873. +               string_table + sym->s.stringoffset,
  1874. +               sym->offset,
  1875. +               member->info.offset);
  1876. +           abort();
  1877. +         }
  1878. +     }
  1879. +       free_name_strings (&file_name);
  1880. +       free (tmp_name);
  1881. +     }
  1882. + }
  1883. + #endif /* DEBUG */
  1884.   void
  1885.   read_old_symdefs (map, archive_indesc)
  1886.        struct mapelt *map;
  1887. ***************
  1888. *** 1451,1474 ****
  1889.   {
  1890.     struct mapelt *mapelt;
  1891.     char *data;
  1892. -   int val;
  1893.     int symdefs_size;
  1894.   
  1895. !   mapelt = find_mapelt_noerror (map, "__.SYMDEF");
  1896.     if (!mapelt)
  1897.       abort ();            /* Only call here if an old one exists */
  1898.   
  1899.     data  = (char *) xmalloc (mapelt->info.size);
  1900.     lseek (archive_indesc, mapelt->info.data_offset, 0);
  1901. !   val = read (archive_indesc, data, mapelt->info.size);
  1902.   
  1903.     symdefs_size = *(unsigned long int *) data;
  1904.     original_num_symdefs = symdefs_size / sizeof (struct symdef);
  1905.     old_symdefs = (struct symdef *) (data + sizeof (symdefs_size));
  1906. -   old_strings = ((char *) (old_symdefs + original_num_symdefs)
  1907. -          + sizeof (symdefs_size));
  1908.     old_strings_size
  1909.       = *(unsigned long int *) (old_symdefs + original_num_symdefs);
  1910.   }
  1911.   
  1912.   /* Read various information from the header of an object file.
  1913. --- 1766,1793 ----
  1914.   {
  1915.     struct mapelt *mapelt;
  1916.     char *data;
  1917.     int symdefs_size;
  1918.   
  1919. !   mapelt = find_mapelt_noerror (map, &symdef_name);
  1920.     if (!mapelt)
  1921.       abort ();            /* Only call here if an old one exists */
  1922.   
  1923.     data  = (char *) xmalloc (mapelt->info.size);
  1924.     lseek (archive_indesc, mapelt->info.data_offset, 0);
  1925. !   if (read (archive_indesc, data, mapelt->info.size) !=
  1926. !       mapelt->info.size)
  1927. !     pfatal_with_name (archive);
  1928.   
  1929.     symdefs_size = *(unsigned long int *) data;
  1930.     original_num_symdefs = symdefs_size / sizeof (struct symdef);
  1931.     old_symdefs = (struct symdef *) (data + sizeof (symdefs_size));
  1932.     old_strings_size
  1933.       = *(unsigned long int *) (old_symdefs + original_num_symdefs);
  1934. +   old_strings = ((char *) (old_symdefs + original_num_symdefs)
  1935. +          + sizeof (old_strings_size));
  1936. + #if DEBUG
  1937. +   verify_symdefs (map, old_symdefs, original_num_symdefs, old_strings);
  1938. + #endif
  1939.   }
  1940.   
  1941.   /* Read various information from the header of an object file.
  1942. ***************
  1943. *** 1475,1481 ****
  1944.      Return 0 for failure or 1 for success.  */
  1945.   
  1946.   int
  1947. ! read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset, strs_size)
  1948.        struct mapelt *mapelt;
  1949.        int desc;
  1950.        long int offset;
  1951. --- 1794,1801 ----
  1952.      Return 0 for failure or 1 for success.  */
  1953.   
  1954.   int
  1955. ! read_header_info (mapelt, desc, offset, syms_offset, syms_size, strs_offset,
  1956. !           strs_size)
  1957.        struct mapelt *mapelt;
  1958.        int desc;
  1959.        long int offset;
  1960. ***************
  1961. *** 1563,1569 ****
  1962.        int archive_indesc;
  1963.   {
  1964.     int indesc;
  1965. -   char *name = mapelt->info.name;
  1966.     long int syms_offset, strs_offset;
  1967.     unsigned int syms_size, strs_size;
  1968.     struct nlist *symbols;
  1969. --- 1883,1888 ----
  1970. ***************
  1971. *** 1572,1581 ****
  1972.     register unsigned int i;
  1973.     unsigned long int offset;
  1974.   
  1975. !   if (name == 0)
  1976. !     /* Deleted member.  */
  1977. !     abort ();
  1978.   
  1979.     if (mapelt->info.offset != 0)
  1980.       {
  1981.         indesc = archive_indesc;
  1982. --- 1891,1902 ----
  1983.     register unsigned int i;
  1984.     unsigned long int offset;
  1985.   
  1986. !   if (marked_for_deletion (mapelt))
  1987. !     fatal ("trying to make symdefs for deleted member");
  1988.   
  1989. +   /* Either use an existing member from the archive, or use the 
  1990. +      user-specified file.  */
  1991.     if (mapelt->info.offset != 0)
  1992.       {
  1993.         indesc = archive_indesc;
  1994. ***************
  1995. *** 1584,1599 ****
  1996.       }
  1997.     else
  1998.       {
  1999. !       indesc = open (mapelt->info.name, 0, 0);
  2000.         if (indesc < 0)
  2001.       {
  2002. !       perror_with_name (mapelt->info.name);
  2003.         return;
  2004.       }
  2005.         offset = 0;
  2006.       }
  2007.   
  2008. !   if (!read_header_info (mapelt, indesc, offset, &syms_offset, &syms_size, &strs_offset, &strs_size))
  2009.       {
  2010.         if (mapelt->info.offset == 0)
  2011.       close (indesc);
  2012. --- 1905,1922 ----
  2013.       }
  2014.     else
  2015.       {
  2016. !       assert (mapelt->info.name.given != NULL);
  2017. !       indesc = open (mapelt->info.name.given, O_RDONLY, 0);
  2018.         if (indesc < 0)
  2019.       {
  2020. !       perror_with_name (mapelt->info.name.given);
  2021.         return;
  2022.       }
  2023.         offset = 0;
  2024.       }
  2025.   
  2026. !   if (!read_header_info (mapelt, indesc, (long) offset, &syms_offset,
  2027. !              &syms_size, &strs_offset, &strs_size))
  2028.       {
  2029.         if (mapelt->info.offset == 0)
  2030.       close (indesc);
  2031. ***************
  2032. *** 1641,1647 ****
  2033.       (void) close (indesc);
  2034.   
  2035.     /* Discard the symbols we don't want to mention; compact the rest down.  */
  2036. !   symcount = filter_symbols (symbols, symcount);
  2037.   
  2038.     mapelt->info.symdefs = (struct symdef *)
  2039.       xmalloc (symcount * sizeof (struct symdef));
  2040. --- 1964,1970 ----
  2041.       (void) close (indesc);
  2042.   
  2043.     /* Discard the symbols we don't want to mention; compact the rest down.  */
  2044. !   symcount = filter_symbols (symbols, (unsigned) symcount);
  2045.   
  2046.     mapelt->info.symdefs = (struct symdef *)
  2047.       xmalloc (symcount * sizeof (struct symdef));
  2048. ***************
  2049. *** 1699,1704 ****
  2050. --- 2022,2028 ----
  2051.     unsigned int len;
  2052.     struct symdef *s;
  2053.     unsigned long int deleted_strings_size = 0;
  2054. +   unsigned long *newoffsets = 0;
  2055.   
  2056.     nsymdefs = original_num_symdefs;
  2057.     num_old_symdefs = original_num_symdefs;
  2058. ***************
  2059. *** 1708,1721 ****
  2060.       {
  2061.         /* We already had a __.SYMDEF member, so just update it.  */
  2062.   
  2063. !       /* Mark as canceled any old symdefs for members being deleted.  */
  2064.   
  2065.         for (tail = map; tail != 0; tail = tail->next)
  2066.       {
  2067. !       if (tail->info.name == 0)
  2068.           {
  2069.             /* Old member being deleted.  Delete its symdef entries too.  */
  2070. !           for (i = 0; i < nsymdefs; i++)
  2071.           if (old_symdefs[i].offset == tail->info.offset)
  2072.             {
  2073.               old_symdefs[i].offset = 0;
  2074. --- 2032,2046 ----
  2075.       {
  2076.         /* We already had a __.SYMDEF member, so just update it.  */
  2077.   
  2078. !       /* Mark as cancelled any old symdefs for members being deleted.  */
  2079.   
  2080.         for (tail = map; tail != 0; tail = tail->next)
  2081.       {
  2082. !       if (marked_for_deletion (tail))
  2083.           {
  2084. +           assert (tail->info.offset != 0);
  2085.             /* Old member being deleted.  Delete its symdef entries too.  */
  2086. !           for (i = 0; i < original_num_symdefs; i++)
  2087.           if (old_symdefs[i].offset == tail->info.offset)
  2088.             {
  2089.               old_symdefs[i].offset = 0;
  2090. ***************
  2091. *** 1744,1751 ****
  2092.         for (tail = map; tail != 0; tail = tail->next)
  2093.       {
  2094.         if (tail->info.offset != 0
  2095. !           || tail->info.name == 0
  2096. !           || !strcmp (tail->info.name, "__.SYMDEF"))
  2097.           continue;
  2098.         make_new_symdefs (tail, archive_indesc);
  2099.         nsymdefs += tail->info.nsymdefs;
  2100. --- 2069,2076 ----
  2101.         for (tail = map; tail != 0; tail = tail->next)
  2102.       {
  2103.         if (tail->info.offset != 0
  2104. !           || marked_for_deletion (tail)
  2105. !           || name_match (&tail->info.name, &symdef_name))
  2106.           continue;
  2107.         make_new_symdefs (tail, archive_indesc);
  2108.         nsymdefs += tail->info.nsymdefs;
  2109. ***************
  2110. *** 1758,1765 ****
  2111.   
  2112.         for (tail = map; tail != 0; tail = tail->next)
  2113.       {
  2114. !       if (tail->info.name == 0
  2115. !           || !strcmp (tail->info.name, "__.SYMDEF"))
  2116.           continue;
  2117.         make_new_symdefs (tail, archive_indesc);
  2118.         nsymdefs += tail->info.nsymdefs;
  2119. --- 2083,2090 ----
  2120.   
  2121.         for (tail = map; tail != 0; tail = tail->next)
  2122.       {
  2123. !       if (marked_for_deletion (tail)
  2124. !           || name_match (&tail->info.name, &symdef_name))
  2125.           continue;
  2126.         make_new_symdefs (tail, archive_indesc);
  2127.         nsymdefs += tail->info.nsymdefs;
  2128. ***************
  2129. *** 1770,1779 ****
  2130.     new_strings_size -= deleted_strings_size;
  2131.     old_strings_size -= deleted_strings_size;
  2132.   
  2133.     /* Now we know the size of __.SYMDEF,
  2134.        so assign the positions of all the members.  */
  2135.   
  2136. !   tail = find_mapelt_noerror (map, "__.SYMDEF");
  2137.     tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef))
  2138.                + sizeof (new_strings_size) + new_strings_size);
  2139.     symdef_mapelt = tail;
  2140. --- 2095,2108 ----
  2141.     new_strings_size -= deleted_strings_size;
  2142.     old_strings_size -= deleted_strings_size;
  2143.   
  2144. + #if DEBUG
  2145. +   verify_symdefs (map, old_symdefs, num_old_symdefs, old_strings);
  2146. + #endif
  2147.     /* Now we know the size of __.SYMDEF,
  2148.        so assign the positions of all the members.  */
  2149.   
  2150. !   tail = find_mapelt_noerror (map, &symdef_name);
  2151.     tail->info.size = (sizeof (nsymdefs) + (nsymdefs * sizeof (struct symdef))
  2152.                + sizeof (new_strings_size) + new_strings_size);
  2153.     symdef_mapelt = tail;
  2154. ***************
  2155. *** 1781,1788 ****
  2156.     pos = SARMAG;
  2157.     for (tail = map; tail != 0; tail = tail->next)
  2158.       {
  2159. !       if (tail->info.name == 0)
  2160. !     /* Ignore deleted members.  */
  2161.       continue;
  2162.         tail->info.new_offset = pos;
  2163.         pos += sizeof (struct ar_hdr) + tail->info.size;
  2164. --- 2110,2116 ----
  2165.     pos = SARMAG;
  2166.     for (tail = map; tail != 0; tail = tail->next)
  2167.       {
  2168. !       if (marked_for_deletion (tail))
  2169.       continue;
  2170.         tail->info.new_offset = pos;
  2171.         pos += sizeof (struct ar_hdr) + tail->info.size;
  2172. ***************
  2173. *** 1790,1815 ****
  2174.       ++pos;
  2175.       }
  2176.   
  2177. !   /* Now update the offsets in the symdef data
  2178. !      to be the new offsets rather than the old ones.  */
  2179.   
  2180.     for (tail = map; tail != 0; tail = tail->next)
  2181.       {
  2182. !       if (tail->info.name == 0)
  2183.       continue;
  2184.         if (tail->info.symdefs == 0)
  2185. !     /* Member without new symdef data.
  2186. !        Check the old symdef data; it may be included there. */
  2187. !     for (i = 0; i < num_old_symdefs; i++)
  2188. !       {
  2189. !         if (old_symdefs[i].offset == tail->info.offset)
  2190. !           old_symdefs[i].offset = tail->info.new_offset;
  2191. !       }
  2192.         else
  2193.       for (i = 0; i < tail->info.nsymdefs; i++)
  2194.         tail->info.symdefs[i].offset = tail->info.new_offset;
  2195.       }
  2196.   
  2197.     /* Generate new, combined string table and put each string's offset into the
  2198.        symdef that refers to it.  Note that old symdefs ref their strings by
  2199.        offsets into old_strings but new symdefs contain addresses of strings.  */
  2200. --- 2118,2166 ----
  2201.       ++pos;
  2202.       }
  2203.   
  2204. !   /* Now update the offsets in the symdef data to be the new offsets
  2205. !      rather than the old ones.  We can't update the old symdefs in
  2206. !      place, because the new offset for one member might match the old
  2207. !      offset for another member.  So for the old symdefs we mark in a
  2208. !      separate array what the new offsets are and then update the
  2209. !      symdefs after going through all the members.  */
  2210. !   newoffsets =
  2211. !     (unsigned long *)xmalloc (num_old_symdefs * sizeof(unsigned long));
  2212. !   bzero (newoffsets, num_old_symdefs * sizeof (unsigned long));
  2213.   
  2214.     for (tail = map; tail != 0; tail = tail->next)
  2215.       {
  2216. !       if (marked_for_deletion (tail))
  2217.       continue;
  2218.         if (tail->info.symdefs == 0)
  2219. !     {
  2220. !       /* Member without new symdef data.
  2221. !          Check the old symdef data; it may be included there. */
  2222. !       assert (tail->info.offset != 0);
  2223. !       for (i = 0; i < num_old_symdefs; i++)
  2224. !         {
  2225. !           if (old_symdefs[i].offset == tail->info.offset)
  2226. !         newoffsets[i] = tail->info.new_offset;
  2227. !         }
  2228. !     }
  2229.         else
  2230.       for (i = 0; i < tail->info.nsymdefs; i++)
  2231.         tail->info.symdefs[i].offset = tail->info.new_offset;
  2232.       }
  2233.   
  2234. +   /* Actually update any old symdefs that have new offsets. */
  2235. +   for (i = 0; i < num_old_symdefs; i++)
  2236. +     if (newoffsets[i] != 0)
  2237. +       old_symdefs[i].offset = newoffsets[i];
  2238. +   free (newoffsets);
  2239. +   newoffsets = 0;
  2240. + #if DEBUG
  2241. +   verify_symdefs (map, old_symdefs, num_old_symdefs, old_strings);
  2242. + #endif
  2243.     /* Generate new, combined string table and put each string's offset into the
  2244.        symdef that refers to it.  Note that old symdefs ref their strings by
  2245.        offsets into old_strings but new symdefs contain addresses of strings.  */
  2246. ***************
  2247. *** 1863,1869 ****
  2248.   {
  2249.     error (s1, s2);
  2250.     fprintf (stderr, "\
  2251. ! Usage: ar [d|m|p|q|r|t|x [[abi [position-name] [cilouv]] archive file...\n");
  2252.     exit (1);
  2253.   }
  2254.   
  2255. --- 2214,2220 ----
  2256.   {
  2257.     error (s1, s2);
  2258.     fprintf (stderr, "\
  2259. ! Usage: ar d|m|p|q|r|t|x [abiclouv] [position-name] archive file...\n");
  2260.     exit (1);
  2261.   }
  2262.   
  2263. ***************
  2264. *** 1896,1904 ****
  2265.     fprintf (stderr, "ar: ");
  2266.     fprintf (stderr, string);
  2267.     if (mapelt->info.offset != 0)
  2268. !     fprintf (stderr, "%s(%s)", archive, mapelt->info.name);
  2269.     else
  2270. !     fprintf (stderr, "%s", mapelt->info.name);
  2271.     fprintf (stderr, "\n");
  2272.   }
  2273.   
  2274. --- 2247,2261 ----
  2275.     fprintf (stderr, "ar: ");
  2276.     fprintf (stderr, string);
  2277.     if (mapelt->info.offset != 0)
  2278. !     {
  2279. !       assert (mapelt->info.name.stored != NULL);
  2280. !       fprintf (stderr, "%s(%s)", archive, mapelt->info.name.stored);
  2281. !     }
  2282.     else
  2283. !     {
  2284. !       assert (mapelt->info.name.given != NULL);
  2285. !       fprintf (stderr, "%s", mapelt->info.name.given);
  2286. !     }
  2287.     fprintf (stderr, "\n");
  2288.   }
  2289.   
  2290. ***************
  2291. *** 1975,1990 ****
  2292.     return result;
  2293.   }
  2294.   
  2295. ! #ifdef    USG
  2296.   int
  2297. ! rename (from, to)
  2298. !      char *from, *to;
  2299.   {
  2300. !   (void)unlink (to);
  2301. !   if (link (from, to) < 0
  2302. !       || unlink (from) < 0)
  2303. !     return -1;
  2304. !   else
  2305.       return 0;
  2306.   }
  2307. ! #endif
  2308. --- 2332,2478 ----
  2309.     return result;
  2310.   }
  2311.   
  2312. ! /* Operations on member_names: */
  2313. ! /* Convert USER_NAME, possibly a path, into the name that goes into
  2314. !    the archive header.  This involves stripping off leading path
  2315. !    information and truncating the final name according to the desired
  2316. !    rules.  The caller is responsible for freeing the returned string. */
  2317. ! char *
  2318. ! user_to_header(user_name)
  2319. !      char *user_name;
  2320. ! {
  2321. !   int namelen;
  2322. !   struct ar_hdr dummy_hdr;
  2323. !   char *result;
  2324. !   char *tmp;
  2325. !   char *file_name;        /* user name after removing initial path */
  2326. !   /* Make a clean copy of the user name.  Bump the pointer past any
  2327. !      leading path information.  */
  2328. !   tmp = concat(user_name, "", "");
  2329. !   user_name = rindex(tmp, '/');
  2330. !   user_name = (user_name ? user_name + 1 : tmp);
  2331. !   /* Save a copy of the file name, in case we need it for an error
  2332. !      message later. */
  2333. !   file_name = concat (user_name, "", "");
  2334. !   /* Truncate the name to fit the ar header size. */
  2335. !   namelen = strlen (user_name);
  2336. !   if (namelen >= sizeof (dummy_hdr.ar_name))
  2337. !     {
  2338. !       if (gnu_truncation
  2339. !       && user_name[namelen - 2] == '.'
  2340. !       && user_name[namelen - 1] == 'o')
  2341. !     {
  2342. !       user_name[sizeof (dummy_hdr.ar_name) - 3] = '.';
  2343. !       user_name[sizeof (dummy_hdr.ar_name) - 2] = 'o';
  2344. !     }
  2345. !       user_name[sizeof (dummy_hdr.ar_name) - 1] = '\0';
  2346. !       error ("Using member name `%s' for filename `%s'", user_name, file_name);
  2347. !     }
  2348. !   /* Now make a fresh copy to return to the user. */
  2349. !   result = concat (user_name, "", "");
  2350. !   free (tmp);
  2351. !   free (file_name);
  2352. !   return result;
  2353. ! }
  2354. ! /* Return non-zero if the member names match.  As a side effect, 
  2355. !    propogates user names.  This side-effect is important for, e.g.,
  2356. !    extracting named members.  */ 
  2357.   int
  2358. ! name_match(name1, name2)
  2359. !      struct member_name *name1, *name2;
  2360.   {
  2361. !   if (strcmp(name1->stored, name2->stored) !=0)
  2362.       return 0;
  2363. +   /* They match. */
  2364. +   if (name1->given && !name2->given)
  2365. +     name2->given = concat (name1->given, "", "");
  2366. +   if (name2->given && !name1->given)
  2367. +     name1->given = concat (name2->given, "", "");
  2368. +   return 1;
  2369.   }
  2370. ! /* Return an array of member names, from an argv-type array of user 
  2371. !    names. */
  2372. ! struct member_name *
  2373. ! make_file_args (argvp, num_files)
  2374. !      char **argvp;
  2375. !      int num_files;            /* number of elements in argvp array */
  2376. ! {
  2377. !   struct member_name *result, *name;
  2378. !   result = (struct member_name *)xmalloc ((num_files + 1) *
  2379. !                       sizeof (struct member_name));
  2380. !   for (name = result; name < result + num_files; ++name, ++argvp)
  2381. !     init_name (name, *argvp);
  2382. !   name->given = NULL;
  2383. !   name->stored = NULL;
  2384. !   return result;
  2385. ! }
  2386. ! /* Initialize a member_name.  The caller is responsible for eventually
  2387. !    freeing the allocated strings.  */
  2388. ! void
  2389. ! init_name (name_ptr, user_name)
  2390. !      struct member_name *name_ptr;
  2391. !      char *user_name;
  2392. ! {
  2393. !   name_ptr->given = concat (user_name, "", "");
  2394. !   name_ptr->stored = user_to_header (user_name);
  2395. ! }
  2396. ! void
  2397. ! free_name_strings (name_ptr)
  2398. !      struct member_name *name_ptr;
  2399. ! {
  2400. !   if (name_ptr->given)
  2401. !     free (name_ptr->given);
  2402. !   if (name_ptr->stored)
  2403. !     free (name_ptr->stored);
  2404. !   name_ptr->given = name_ptr->stored = NULL;
  2405. ! }
  2406. ! /* Methods for managing mapelt's. */
  2407. ! /* Initialize a map element: make sure the name is empty. */
  2408. ! void
  2409. ! init_elt (elt)
  2410. !      struct mapelt *elt;
  2411. ! {
  2412. !   elt->info.name.stored = elt->info.name.given = NULL;
  2413. ! }
  2414. ! /* Mark a map element for deletion by making the name empty.
  2415. !    XXX - leaks some memory here. */
  2416. ! void
  2417. ! mark_as_deleted (elt)
  2418. !      struct mapelt *elt;
  2419. ! {
  2420. !   elt->info.name.stored = elt->info.name.given = NULL;
  2421. ! }
  2422. ! int
  2423. ! marked_for_deletion (elt)
  2424. !      struct mapelt *elt;
  2425. ! {
  2426. !   return Empty_Name(&elt->info.name);
  2427. ! }
  2428.